﻿using DotNetFramework.CAP.Core.Logger;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DotNetFramework.CAP.Core.Ioc;
using System.ComponentModel;
#if AUTO_FAC
using Autofac;
using Autofac.Core;
#else
#endif
using DotNetFramework.CAP;
using DotNetFramework.CAP.Processor.States;
using System.CodeDom.Compiler;

namespace DotnetFramework.CAP.Ioc
{

    public class ServiceProvider : DotNetFramework.CAP.Core.Ioc.IServiceProvider
    {
        static IServiceCollection _gloabServices;
        IServiceCollection _services;
        public IServiceCollection ServiceCollection
        {
            get
            {
                if (_services == null)
                    return _gloabServices;
                return _services;
            }
            set
            {
                if (value != null)
                {
                    _gloabServices = value;
                }
                _services = value;
            }
        }
        private IServiceScope Root { set; get; }
        private IocRefction.IContainer _container;
        public IocRefction.IContainer Container
        {
            set
            {
                _container = value;
                //var scope = _container.BeginLifetimeScope();
                //_root = scope;
                Root = new ServiceScope();
                Root.ServiceProvider = this;
            }
            get
            {
                return _container;
            }
        }

        public ServiceProvider()
        {
            if (Container == null)
                Container = GlobalContainer;
        }
        public ServiceProvider(/*Autofac.ILifetimeScope scope,*/ IocRefction.IContainer container)
        {
            //if (scope != null)
            //    Scope = scope;
            Container = container;
            GlobalContainer = _container;
        }

        public IServiceScope CreateScope()
        {
            var _serviceScope = new ServiceScope();
            _serviceScope.ServiceProvider = new ServiceProvider(_container);
            //_serviceScope.ServiceProvider.Container = this._container;
            //_serviceScope.ServiceProvider.Scope = _scope;
            _serviceScope.ServiceProvider.ServiceCollection = this.ServiceCollection;
            return _serviceScope;
        }
        public static IocRefction.IContainer GlobalContainer;
        public T GetRequiredService<T>()
        {
            return _container.Resolve<T>();
        }

        public T GetService<T>()
        {
            try
            {
                if (typeof(T) == (typeof(IBootstrapper)))
                {
                    //var log = _root.Resolve<ILogger>();
                    //var storage = _root.Resolve<IStorage>();

                    //var consumerClientFactory = _root.Resolve<IConsumerClientFactory>();
                    //var options = _root.Resolve<CapOptions>();
                    //var stateChanger = _root.Resolve<IStateChanger>();
                    //var connection = _root.Resolve<IStorageConnection>();

                    //var f1 = _root.Resolve<DotNetFramework.CAP.Core.Logger.ILoggerFactory>();
                    //var f2 = _root.Resolve < DotNetFramework.CAP.Abstractions.IMessagePacker>();
                    //var f3 = _root.Resolve < DotNetFramework.CAP.Abstractions.IModelBinderFactory>();
                    //var f = _root.IsRegistered<DotNetFramework.CAP.Core.Ioc.IServiceProvider>();

                    //var t=_root.ResolveOptional<DotNetFramework.CAP.Core.Ioc.IServiceProvider>();
                    //var f40 = _root.Resolve<DotNetFramework.CAP.Core.Ioc.IServiceProvider>();
                    //var sender = _root.Resolve<IPublishMessageSender>();
                    //var executor = _root.Resolve<ISubscriberExecutor>();
                    //var dispatcher = _root.Resolve<IDispatcher>();
                    //var selector = _root.Resolve<DotNetFramework.CAP.Internal.MethodMatcherCache>();
                    //var processors = _root.Resolve<IEnumerable<IProcessingServer>>();
                }
                return _container.Resolve<T>();
            }
            catch { return default(T); }
        }

        public object GetService(Type serviceType)
        {
            try
            {
                return _container.Resolve(serviceType);
            }
            catch
            {
                //Log.Warning(serviceType.FullName);
                return null;
            }
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            foreach (var item in ServiceCollection)
            {
                if (item.ServiceType == serviceType)
                {
                    var impl = GetServiceByName(item.ImplementationType.FullName, serviceType);
                    if (impl != null)
                        yield return impl;
                }

            }
        }

        private object GetServiceByName(string Name, Type serviceType)
        {
            try
            {
                return _container.ResolveNamed(Name, serviceType);
            }
            catch
            {
                //Log.Warning(serviceType.FullName);
                return null;
            }
        }


        public IEnumerable<object> GetServices<T>()
        {
            return this.GetServices(typeof(T));
        }
    }
}
